package com.dot.dominion;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Application;
import android.util.Log;

import com.dot.dominion.database.CardDatabase;
import com.dot.dominion.domain.Card;
import com.dot.dominion.domain.Deck;
import com.dot.dominion.domain.Hand;
import com.dot.dominion.domain.Player;
import com.dot.dominion.domain.PlayingDeck;
import com.dot.dominion.domain.SupplyPile;
import com.dot.dominion.domain.Trash;
import com.dot.dominion.domain.players.Player1;
import com.dot.dominion.domain.players.Player2;
import com.dot.dominion.domain.players.Player3;
import com.dot.dominion.domain.players.Player4;
import com.dot.dominion.exception.DominionException;

public class Game extends Application {
	//FOR TESTING PURPOSES ONLY
	private static final int BOARD_SIZE = 6;
  
  private Map<Player, Deck> _playingFields;
  private Map<Player, PlayingDeck> _playingDecks;
  private Map<Player, Hand> _hands;
  
  private Map<Integer, SupplyPile> _supplies;
  
  private Trash _trash = new Trash();
  private List<Player> _players = new ArrayList<Player>(4);
  private int _counter = 0;
  
  @Override
  public void onCreate() {
	  super.onCreate();
	  
	  _playingFields = new HashMap<Player, Deck>(4);
	  _playingDecks = new HashMap<Player, PlayingDeck>(4);
	  _hands = new HashMap<Player, Hand>(4);
	  //_supplies = new HashMap<String, SupplyPile>(16);
	  
	  //Only for testing purposes
	  _supplies = new HashMap<Integer, SupplyPile>(Constants.TESTING_BOARD_SIZE);
	  
	  setupSupplies();
	  
	  try {
		  setupGame(2);
	  } catch( DominionException e ) {
		  //stfu dominion exception lol
	  }
  }
	
	public List<Card> getBoardList() {
		ArrayList<Card> list = new ArrayList<Card>();
		
		for(int i = 0; i < Constants.BOARD_SIZE; i++) {
			Integer integer = new Integer(i);
			Log.d("DEBUGTAG", "number"+i);
			list.add( _supplies.get(integer).peekAtTop() );
		}
		
		return list;
	}
	
	public Hand getHand(int playerNumber ) {
		Hand hand = null;
		
		switch( playerNumber ) {
			case Constants.PLAYER_ONE:
				hand = _hands.get(Player1.getInstance());
				break;
			case Constants.PLAYER_TWO:
				hand = _hands.get(Player2.getInstance());
				break;
			case Constants.PLAYER_THREE:
				hand = _hands.get(Player3.getInstance());
				break;
			case Constants.PLAYER_FOUR:
				hand = _hands.get(Player4.getInstance());
				break;
		}
		
		return hand;
	}
	
  	//creates the default decks
	private PlayingDeck setupDefaultDeck () {
		PlayingDeck deck = new PlayingDeck();
		SupplyPile coppers = _supplies.get(Constants.SUPPLY_COPPER);
		SupplyPile estates = _supplies.get(Constants.SUPPLY_ESTATE);
		
		for (int i = 0; i < 7; ++i)
			deck.addToDeck( coppers.getCard() );
	  
		for (int i = 0; i < 3; ++i)
			deck.addToDeck( estates.getCard() );
		
    	deck.shuffle();
    	
    	return deck;
	}
	
	 //initializes all the fields for each player
	private void setupGame (int numPlayers) throws DominionException {
	    switch (numPlayers) {
	      case 4:
	        _players.add(0, Player4.getInstance());
	        PlayingDeck player4Deck = setupDefaultDeck();
	        _playingDecks.put(Player4.getInstance(), player4Deck);
	        _playingFields.put(Player4.getInstance(), new Deck());
	        Hand player4Hand = new Hand();
	        for (int i = 0; i < 5; ++i) {
	          player4Hand.addToHand(player4Deck.draw());
	        }
	        _hands.put(Player4.getInstance(), player4Hand);
	      case 3:
	        _players.add(0, Player3.getInstance());
	        PlayingDeck player3Deck = setupDefaultDeck();
	        _playingDecks.put(Player3.getInstance(), player3Deck);
	        _playingFields.put(Player3.getInstance(), new Deck());
	        Hand player3Hand = new Hand();
	        for (int i = 0; i < 5; ++i) {
	          player3Hand.addToHand(player3Deck.draw());
	        }
	        _hands.put(Player3.getInstance(), player3Hand);
	      case 2:
	        _players.add(0, Player2.getInstance());
	        PlayingDeck player2Deck = setupDefaultDeck();
	        _playingDecks.put(Player2.getInstance(), player2Deck);
	        _playingFields.put(Player2.getInstance(), new Deck());
	        Hand player2Hand = new Hand();
	        for (int i = 0; i < 5; ++i) {
	          player2Hand.addToHand(player2Deck.draw());
	        }
	        _hands.put(Player2.getInstance(), player2Hand);
	      case 1:
	        _players.add(0, Player1.getInstance());
	        PlayingDeck player1Deck = setupDefaultDeck();
	        _playingDecks.put(Player1.getInstance(), player1Deck);
	        _playingFields.put(Player1.getInstance(), new Deck());
	        Hand player1Hand = new Hand();
	        for (int i = 0; i < 5; ++i) {
	          player1Hand.addToHand(player1Deck.draw());
	        }
	        _hands.put(Player1.getInstance(), player1Hand);
	        break;
	      default:
	        throw new DominionException("INVALID GAME PARAMETERS: Someone attempted to create a game "
	                                    + "with " + numPlayers + ".");
	    }
	  }
	
	private void setupSupplies() {		
		setupTestPiles();
	}
	
	private void setupTestPiles() {
		ArrayList<String> requestList = new ArrayList<String>();
		
		//The requested list of supply piles
		requestList.add("copper");
		requestList.add("silver");
		requestList.add("gold");
		requestList.add("estate");
		requestList.add("duchy");
		requestList.add("province");
		requestList.add("curse");
		
		CardDatabase database = new CardDatabase( getResources(),
											R.raw.carddatabase, requestList );
		List<Card> cardList = database.getCardList();
		
		/*Test Cards*/
		cardList.add(new Card("H", R.drawable.be08, R.drawable.be08bv, 0, 0, 0));
		cardList.add(new Card("I", R.drawable.be10,R.drawable.be10bv, 0, 0, 0));
		cardList.add(new Card("J", R.drawable.be12,R.drawable.be12bv, 0, 0, 0));
		cardList.add(new Card("K", R.drawable.be18,R.drawable.be18bv, 0, 0, 0));
		cardList.add(new Card("L", R.drawable.be22,R.drawable.be22bv, 0, 0, 0));
		cardList.add(new Card("M", R.drawable.be24,R.drawable.be24bv, 0, 0, 0));
		cardList.add(new Card("N", R.drawable.be12,R.drawable.be12bv, 0, 0, 0));
		cardList.add(new Card("O", R.drawable.be18,R.drawable.be18bv, 0, 0, 0));
		cardList.add(new Card("P", R.drawable.be22,R.drawable.be22bv,  0, 0, 0));
		cardList.add(new Card("Q", R.drawable.be24, R.drawable.be24bv,0, 0, 0));

		Log.d("DEBUGTAG", "CardList.size()--"+cardList.size());
		
		SupplyPile pile;
		int pileNumber = 1;
		while(! cardList.isEmpty()) {
			Card card = cardList.remove(0);
			
			if( card.getName().equalsIgnoreCase("copper") ) {
				pile = new SupplyPile(card, Constants.SETUP_COPPER);
				_supplies.put(Constants.SUPPLY_COPPER, pile);
			}
			else if( card.getName().equalsIgnoreCase("silver") ) {
				pile = new SupplyPile(card, Constants.SETUP_SILVER);
				_supplies.put(Constants.SUPPLY_SILVER, pile);
			}
			else if( card.getName().equalsIgnoreCase("gold") ) {
				pile = new SupplyPile(card, Constants.SETUP_GOLD);
				_supplies.put(Constants.SUPPLY_GOLD, pile);
			}
			else if( card.getName().equalsIgnoreCase("estate") ) {
				pile = new SupplyPile(card, Constants.SETUP_ESTATE_34);
				_supplies.put(Constants.SUPPLY_ESTATE, pile);
			}
			else if( card.getName().equalsIgnoreCase("duchy") ) {
				pile = new SupplyPile(card, Constants.SETUP_DUCHY_34);
				_supplies.put(Constants.SUPPLY_DUCHY, pile);
			}
			else if( card.getName().equalsIgnoreCase("province") ) {
				pile = new SupplyPile(card, Constants.SETUP_PROVINCE_34);
				_supplies.put(Constants.SUPPLY_PROVINCE, pile);
			}
			else if( card.getName().equalsIgnoreCase("curse") ) {
				pile = new SupplyPile(card, Constants.SETUP_DUCHY_34);
				_supplies.put(Constants.SUPPLY_CURSE, pile);
			}
			else {
				pile = new SupplyPile(card, Constants.STARTING_SUPPLY_SIZE);
				
				switch(pileNumber) {
					case 1:
						_supplies.put(Constants.SUPPLY_PILE1, pile);
						break;
					case 2:
						_supplies.put(Constants.SUPPLY_PILE2, pile);
						break;
					case 3:
						_supplies.put(Constants.SUPPLY_PILE3, pile);
						break;
					case 4:
						_supplies.put(Constants.SUPPLY_PILE4, pile);
						break;
					case 5:
						_supplies.put(Constants.SUPPLY_PILE5, pile);
						break;
					case 6:
						_supplies.put(Constants.SUPPLY_PILE6, pile);
						break;
					case 7:
						_supplies.put(Constants.SUPPLY_PILE7, pile);
						break;
					case 8:
						_supplies.put(Constants.SUPPLY_PILE8, pile);
						break;
					case 9:
						_supplies.put(Constants.SUPPLY_PILE9, pile);
						break;
					case 10:
						_supplies.put(Constants.SUPPLY_PILE10, pile);
						break;
				}
				
				++pileNumber;
			}
		}
		
		//Setup filler images
		Card card = (new Card("FILLER", R.drawable.be08, R.drawable.be08bv,0, 0, 0));
		pile = new SupplyPile(card, Constants.STARTING_SUPPLY_SIZE);
		_supplies.put(Constants.SUPPLY_FILLER, pile);
		//Setup Trash images
		Card trash = (new Card("TRASH", R.drawable.be08,R.drawable.be24bv, 0, 0, 0));
		pile = new SupplyPile(trash, Constants.STARTING_SUPPLY_SIZE);
		_supplies.put(Constants.SUPPLY_TRASH, pile);
	}
	
	public Card viewSupplyPile(int position) {
		SupplyPile pile = _supplies.get( position );
		
		return pile.peekAtTop();
	}
}
